import 'dart:async';

import 'package:flutter/material.dart';
import 'package:xws/helpers/safe_state.dart';
import 'package:xws/helpers/safe_value_notifier.dart';
import 'package:xws/models/app_enum.dart';
import 'package:xws/utils/theme_util.dart';
import 'package:xws/widgets/ex_value_builder.dart';
import 'package:xws/widgets/refresh_widget/loading_view.dart';

///轮播图
class AppSwiper<T> extends StatefulWidget {
  const AppSwiper({
    Key? key,
    required this.itemBuilder,
    required this.onReady,
    this.animatesDuration = const Duration(milliseconds: 1000),
    this.switchDuration = const Duration(seconds: 4),
    this.swiperController,
    this.viewportFraction = 1,
    this.withIndicator = true,
    this.onTap,
  }) : super(key: key);

  @override
  _AppSwiperState<T> createState() => _AppSwiperState<T>();

  final Widget Function(T, int) itemBuilder;

  final Future<List<T>> Function() onReady;

  final Function(T object)? onTap;

  final Duration animatesDuration;

  final Duration switchDuration;

  final SwiperController<T>? swiperController;

  final double viewportFraction;

  final bool withIndicator;
}

class _AppSwiperState<T> extends State<AppSwiper<T>> with SafeState<AppSwiper<T>> {
  late PageController _swiperController;

  final List<T> _dataList = <T>[];

  PageState _swiperState = PageState.loading;

  late SafeValueNotifier<int> _page;

  Timer? _timer;
  bool _isPause = false;
  bool _canScroll = true;

  @override
  void initState() {
    super.initState();
    _swiperController = PageController(
      initialPage: 1000,
      viewportFraction: widget.viewportFraction,
    );

    _page = SafeValueNotifier<int>(0);
  }

  @override
  Future<void> contextReady() async {
    await _refresh();
    return super.contextReady();
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    if (widget.swiperController != null) {
      widget.swiperController?._appSwiperState = this;
    }
  }

  @override
  void dispose() {
    _swiperController.dispose();
    _page.dispose();
    _cancelTimer();
    super.dispose();
  }

  ///刷新
  Future<void> _refresh() async {
    final List<T> temp = await widget.onReady();
    if (!mounted) return;

    if (temp.isNotEmpty) {
      _dataList.clear();
      _dataList.addAll(temp);
      _swiperState = PageState.normal;

      _cancelTimer();

      if (temp.length > 1) {
        _startTimer();
      } else {
        _canScroll = false;
      }
    } else {
      _swiperState = PageState.empty;
    }

    safeSetState(() {});
  }

  ///取消计时器
  void _cancelTimer() {
    _timer?.cancel();
    _timer = null;
  }

  ///启动计时器
  void _startTimer() {
    _timer = Timer.periodic(widget.switchDuration, (_) async {
      if (!_isPause) {
        if (_swiperController.page! >= 1000 + _dataList.length) {
          _swiperController.jumpToPage(1000);
        }

        await _swiperController.nextPage(duration: widget.animatesDuration, curve: Curves.ease);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    if (_swiperState == PageState.loading) return const LoadingView();
    if (_swiperState == PageState.normal) return _normalView;

    return _buildEmpty;
  }

  ///常规视图
  Widget get _normalView {
    return Listener(
      onPointerDown: (_) {
        if (!_isPause) {
          _isPause = true;
          _cancelTimer();
        }
      },
      onPointerUp: (_) {
        if (_isPause) {
          _isPause = false;
          if (_dataList.length > 1) _startTimer();
        }
      },
      child: Stack(
        alignment: Alignment.bottomCenter,
        children: <Widget>[
          PageView.builder(
            physics: _canScroll ? null : const NeverScrollableScrollPhysics(),
            controller: _swiperController,
            itemBuilder: (_, int index) {
              final T data = _dataList[index % _dataList.length];
              Widget item = widget.itemBuilder(data, index);

              if (widget.onTap != null) {
                item = GestureDetector(
                  onTap: () => widget.onTap?.call(data),
                  child: item,
                );
              }

              return item;
            },
            onPageChanged: (int p) => _page.value = p % 1000 % _dataList.length,
          ),
          Padding(
            padding: const EdgeInsets.only(bottom: 8),
            child: ExValueBuilder<int>(
              valueListenable: _page,
              builder: (_, int page, __) {
                final int p = page % 1000 % _dataList.length;

                return Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    for (int i = 0; i < _dataList.length; i++)
                      AnimatedContainer(
                        duration: const Duration(milliseconds: 200),
                        width: p == i ? 14 : 8,
                        height: 5,
                        margin: const EdgeInsets.symmetric(horizontal: 3),
                        decoration: BoxDecoration(
                          color: white(context).withOpacity(p == i ? 1 : 0.5),
                          borderRadius: BorderRadius.circular(5),
                        ),
                      ),
                  ],
                );
              },
            ),
          ),
        ],
      ),
    );
  }

  /// 空视图
  Widget get _buildEmpty {
    return GestureDetector(
      onTap: _refresh,
      child: PageView.builder(
        controller: _swiperController,
        itemBuilder: (_, __) => _emptyItem,
      ),
    );
  }

  /// 空视图项
  Widget get _emptyItem {
    return Container(
      alignment: Alignment.center,
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Icon(
            Icons.layers_rounded,
            size: 26,
            color: black(context).withOpacity(0.1),
          ),
          const SizedBox(width: 14),
          const Text('点击重试', style: TextStyle(fontSize: 14)),
        ],
      ),
      margin: const EdgeInsets.symmetric(horizontal: 8),
      decoration: BoxDecoration(
        color: white(context),
        borderRadius: BorderRadius.circular(10),
      ),
    );
  }
}

///轮播图控制器
class SwiperController<T> {
  _AppSwiperState<T>? _appSwiperState;

  Future<void> refresh() async {
    await _appSwiperState?._refresh();
  }

  void dispose() {
    _appSwiperState = null;
  }
}
